package com.ruyiadmin.springcloud.producer.controller.system;

import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.ruyiadmin.springcloud.producer.common.annotations.system.Log;
import com.ruyiadmin.springcloud.producer.common.annotations.system.Permission;
import com.ruyiadmin.springcloud.producer.common.beans.system.SystemCacheConfig;
import com.ruyiadmin.springcloud.producer.common.components.core.RuYiRedisComponent;
import com.ruyiadmin.springcloud.producer.common.components.core.RuYiSessionContext;
import com.ruyiadmin.springcloud.producer.common.core.business.enums.DeletionType;
import com.ruyiadmin.springcloud.producer.common.core.business.enums.OperationType;
import com.ruyiadmin.springcloud.producer.common.core.business.enums.RoleType;
import com.ruyiadmin.springcloud.producer.common.core.system.entities.*;
import com.ruyiadmin.springcloud.producer.common.core.system.enums.DataType;
import com.ruyiadmin.springcloud.producer.common.core.system.enums.QueryMethod;
import com.ruyiadmin.springcloud.producer.common.exceptions.RuYiAdminCustomException;
import com.ruyiadmin.springcloud.producer.common.utils.core.RuYiFileUtil;
import com.ruyiadmin.springcloud.producer.common.utils.core.RuYiPoiUtil;
import com.ruyiadmin.springcloud.producer.domain.dto.system.ImportConfigDTO;
import com.ruyiadmin.springcloud.producer.domain.dto.system.SysRoleDTO;
import com.ruyiadmin.springcloud.producer.domain.dto.system.SysUserDTO;
import com.ruyiadmin.springcloud.producer.domain.entity.system.*;
import com.ruyiadmin.springcloud.producer.service.iservices.system.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.modelmapper.ModelMapper;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 前端控制器
 * </p>
 *
 * @author RuYiAdmin
 * @since 2022-07-12
 */
@RestController
@RequestMapping("/RoleManagement")
@Api(tags = "系统角色管理服务")
@RequiredArgsConstructor
public class SysRoleController {

    //region 角色服务私有属性

    private final RuYiRedisComponent redisUtils;
    private final SystemCacheConfig systemCacheConfig;
    private final ISysRoleService roleService;
    private final ISysRoleOrgService roleOrgService;
    private final ISysRoleUserService roleUserService;
    private final ISysRoleMenuService roleMenuService;
    private final RuYiSessionContext sessionContext;
    private final ModelMapper modelMapper;
    private final ISysImportConfigService importConfigService;

    //endregion

    //region 查询角色列表

    @PostMapping("/Post")
    @ApiOperation(value = "查询角色列表")
    @Log(OperationType = OperationType.QueryList)
    @Permission(permission = "role:query:list")
    public QueryResult<SysRoleDTO> queryOrgRoleInfo(@RequestBody QueryCondition queryCondition) throws Exception {
        if (queryCondition.getQueryItems().size() <= 0) {
            queryCondition.setQueryItems(new ArrayList<>());
        }
        String orgId = this.sessionContext.getUserOrgId();
        queryCondition.getQueryItems().add(new QueryItem("ORG_ID", DataType.Guid, QueryMethod.Equal, orgId));
        return this.roleService.queryOrgRoleInfo(queryCondition);
    }

    //endregion

    //region 查询角色信息

    @GetMapping("/GetById/{roleId}")
    @ApiOperation(value = "查询角色信息")
    @Log(OperationType = OperationType.QueryEntity)
    @Permission(permission = "role:query:list")
    public ActionResult getById(@PathVariable("roleId") String roleId)
            throws ExecutionException, InterruptedException {
        CompletableFuture<ActionResult> future = CompletableFuture.supplyAsync(() -> {
            Object value = this.redisUtils.get(systemCacheConfig.getRoleCacheName());
            List<SysRoleDTO> roles = JSON.parseArray(value.toString(), SysRoleDTO.class);

            SysRoleDTO role = roles.stream()
                    .filter(t -> t.getId().equals(roleId))
                    .collect(Collectors.toList())
                    .get(0);

            return ActionResult.success(role);
        });
        return future.get();
    }

    //endregion

    //region 新增系统角色

    @PostMapping("/Add")
    @ApiOperation(value = "新增系统角色")
    @Log(OperationType = OperationType.AddEntity)
    @Permission(permission = "role:add:entity")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult add(@Valid @RequestBody SysRole role) throws Exception {
        //保存角色信息
        this.roleService.save(role);

        //获取用户机构编号
        String orgId = this.sessionContext.getUserOrgId();
        SysRoleOrg roleOrg = new SysRoleOrg();
        roleOrg.setRoleId(role.getId());
        roleOrg.setOrgId(orgId);
        roleOrg.setOwnerType(RoleType.Own.ordinal());
        //保存机构与角色关系
        this.roleOrgService.save(roleOrg);

        //region 数据一致性维护

        Object value = this.redisUtils.get(systemCacheConfig.getRoleCacheName());
        List<SysRoleDTO> roles = JSON.parseArray(value.toString(), SysRoleDTO.class);

        SysRoleDTO roleDTO = this.modelMapper.map(role, SysRoleDTO.class);
        roleDTO.setOrgId(roleOrg.getOrgId());
        //添加新数据
        roles.add(roleDTO);
        //更新缓存
        this.redisUtils.set(systemCacheConfig.getRoleCacheName(), JSON.toJSONString(roles));

        value = this.redisUtils.get(systemCacheConfig.getRoleAndOrgCacheName());
        List<SysRoleOrg> roleOrgs = JSON.parseArray(value.toString(), SysRoleOrg.class);
        //添加新数据
        roleOrgs.add(roleOrg);
        //更新缓存
        this.redisUtils.set(systemCacheConfig.getRoleAndOrgCacheName(), JSON.toJSONString(roleOrgs));

        //endregion

        return ActionResult.ok();
    }

    //endregion

    //region 编辑系统角色

    @PutMapping("/Put")
    @ApiOperation(value = "编辑系统角色")
    @Log(OperationType = OperationType.EditEntity)
    @Permission(permission = "role:edit:entity")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult edit(@Valid @RequestBody SysRole role) {
        //更新角色信息
        this.roleService.updateById(role);

        //region 数据一致性维护

        Object value = this.redisUtils.get(systemCacheConfig.getRoleCacheName());
        List<SysRoleDTO> roles = JSON.parseArray(value.toString(), SysRoleDTO.class);

        SysRoleDTO oldRole = roles.stream().
                filter(t -> t.getId().equals(role.getId())).
                collect(Collectors.toList()).
                get(0);

        //删除旧数据
        for (Iterator<SysRoleDTO> iterator = roles.iterator(); iterator.hasNext(); ) {
            SysRoleDTO element = iterator.next();
            if (element.getId().equals(role.getId())) {
                iterator.remove();
                break;
            }
        }

        //添加新数据
        SysRoleDTO roleDTO = this.modelMapper.map(role, SysRoleDTO.class);
        roleDTO.setOrgId(oldRole.getOrgId());
        roles.add(roleDTO);

        //更新缓存
        this.redisUtils.set(systemCacheConfig.getRoleCacheName(), JSON.toJSONString(roles));

        //endregion

        return ActionResult.ok();
    }

    //endregion

    //region 批量删除角色信息

    @DeleteMapping("/DeleteRange/{ids}")
    @ApiOperation(value = "批量删除角色信息")
    @Log(OperationType = OperationType.DeleteEntity)
    @Permission(permission = "user:del:entities")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult deleteRange(@PathVariable("ids") String ids) {
        //数据删除检测
        this.deleteCheck(ids);

        //删除角色
        List<String> array = Arrays.asList(ids.split(","));
        ActionResult actionResult = ActionResult.success(this.roleService.removeByIds(array));

        //删除角色与机构关系
        Object value = this.redisUtils.get(systemCacheConfig.getRoleAndOrgCacheName());
        List<SysRoleOrg> roleOrgs = JSON.parseArray(value.toString(), SysRoleOrg.class);

        List<SysRoleOrg> dels = new ArrayList<>();
        array.forEach(item -> {
            SysRoleOrg roleOrg = roleOrgs.stream().
                    filter(r -> r.getIsdel() == DeletionType.Undeleted.ordinal()).
                    filter(r -> r.getRoleId().equals(item)).
                    filter(r -> r.getOwnerType() == RoleType.Own.ordinal()).
                    collect(Collectors.toList()).get(0);
            dels.add(roleOrg);
        });

        this.roleOrgService.removeByIds(dels.stream().map(SysRoleOrg::getId).collect(Collectors.toList()));

        //region 数据一致性维护

        //获取角色缓存
        value = this.redisUtils.get(systemCacheConfig.getRoleCacheName());
        List<SysRoleDTO> roles = JSON.parseArray(value.toString(), SysRoleDTO.class);

        array.forEach(item -> {
            //删除旧数据
            for (Iterator<SysRoleDTO> iterator = roles.iterator(); iterator.hasNext(); ) {
                SysRoleDTO element = iterator.next();
                if (element.getId().equals(item)) {
                    iterator.remove();
                    break;
                }
            }
        });
        //更新角色缓存
        this.redisUtils.set(systemCacheConfig.getRoleCacheName(), JSON.toJSONString(roles));

        roleOrgs.removeAll(dels);
        //更新角色与机构缓存
        this.redisUtils.set(systemCacheConfig.getRoleAndOrgCacheName(), JSON.toJSONString(roleOrgs));

        //endregion

        return actionResult;
    }

    //endregion

    //region 角色授权用户

    @PostMapping("/GrantUserRole")
    @ApiOperation(value = "角色授权用户")
    @Log(OperationType = OperationType.PermissionAuthorization)
    @Permission(permission = "role:grant:permission")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult grantUserRole(@Valid @RequestBody List<SysRoleUser> roleUsers) {
        List<SysRoleUser> adds = new ArrayList<>();

        //获取缓存数据
        Object value = this.redisUtils.get(systemCacheConfig.getRoleAndUserCacheName());
        List<SysRoleUser> list = JSON.parseArray(value.toString(), SysRoleUser.class);

        roleUsers.forEach(item -> {
            long count = list.stream().
                    filter(t -> t.getIsdel() == DeletionType.Undeleted.ordinal()).
                    filter(t -> t.getUserId().equals(item.getUserId())).
                    filter(t -> t.getRoleId().equals(item.getRoleId())).
                    count();
            if (count <= 0) {
                adds.add(item);
            }
        });

        //添加角色与用户关系
        this.roleUserService.saveBatch(adds);

        list.addAll(adds);
        //更新缓存
        this.redisUtils.set(systemCacheConfig.getRoleAndUserCacheName(), JSON.toJSONString(list));

        return ActionResult.ok();
    }

    //endregion

    //region 收回用户授权

    @PostMapping("/WithdrawGrantedUserRole")
    @ApiOperation(value = "收回用户授权")
    @Log(OperationType = OperationType.PermissionAuthorization)
    @Permission(permission = "role:grant:permission")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult withdrawGrantedUserRole(@Valid @RequestBody List<SysRoleUser> roleUsers) {
        List<SysRoleUser> dels = new ArrayList<>();

        //获取缓存数据
        Object value = this.redisUtils.get(systemCacheConfig.getRoleAndUserCacheName());
        List<SysRoleUser> list = JSON.parseArray(value.toString(), SysRoleUser.class);

        roleUsers.forEach(item -> {
            List<SysRoleUser> entities = list.stream().
                    filter(t -> t.getIsdel() == DeletionType.Undeleted.ordinal()).
                    filter(t -> t.getUserId().equals(item.getUserId())).
                    filter(t -> t.getRoleId().equals(item.getRoleId())).
                    collect(Collectors.toList());
            if (entities.size() > 0) {
                dels.addAll(entities);
            }
        });

        //添加角色与用户关系
        this.roleUserService.removeByIds(dels);

        //删除旧数据
        dels.forEach(item -> {
            for (Iterator<SysRoleUser> iterator = list.iterator(); iterator.hasNext(); ) {
                SysRoleUser element = iterator.next();
                if (element.getId().equals(item.getId())) {
                    iterator.remove();
                    break;
                }
            }
        });

        //更新缓存
        this.redisUtils.set(systemCacheConfig.getRoleAndUserCacheName(), JSON.toJSONString(list));

        return ActionResult.ok();
    }

    //endregion

    //region 查询角色授权用户

    @GetMapping("/GetGrantedUserRoles/{roleId}")
    @ApiOperation(value = "查询角色授权用户")
    @Log(OperationType = OperationType.QueryList)
    @Permission(permission = "role:grant:permission")
    public ActionResult getGrantedUserRoles(@PathVariable("roleId") String roleId)
            throws ExecutionException, InterruptedException {
        CompletableFuture<ActionResult> future = CompletableFuture.supplyAsync(() -> {
            //获取缓存数据
            Object value = this.redisUtils.get(systemCacheConfig.getRoleAndUserCacheName());
            List<SysRoleUser> list = JSON.parseArray(value.toString(), SysRoleUser.class);

            list = list.stream().
                    filter(t -> t.getIsdel() == DeletionType.Undeleted.ordinal()).
                    filter(t -> t.getRoleId().equals(roleId)).
                    collect(Collectors.toList());

            return ActionResult.success(list);
        });
        return future.get();
    }

    //endregion

    //region 角色关联菜单

    @PostMapping("/GrantRoleMenus")
    @ApiOperation(value = "角色关联菜单")
    @Log(OperationType = OperationType.MenuAuthorization)
    @Permission(permission = "role:relate:menus")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult grantRoleMenus(@Valid @RequestBody List<SysRoleMenu> roleMenus) {
        List<SysRoleMenu> dels = new ArrayList<>();

        //获取缓存数据
        Object value = this.redisUtils.get(systemCacheConfig.getRoleAndMenuCacheName());
        List<SysRoleMenu> list = JSON.parseArray(value.toString(), SysRoleMenu.class);

        List<SysRoleMenu> entities = list.stream().
                filter(t -> t.getIsdel() == DeletionType.Undeleted.ordinal()).
                filter(t -> t.getRoleId().equals(roleMenus.get(0).getRoleId())).
                collect(Collectors.toList());
        if (entities.size() > 0) {
            dels.addAll(entities);
        }

        //删除旧数据
        this.roleMenuService.removeByIds(dels);
        dels.forEach(item -> {
            for (Iterator<SysRoleMenu> iterator = list.iterator(); iterator.hasNext(); ) {
                SysRoleMenu element = iterator.next();
                if (element.getId().equals(item.getId())) {
                    iterator.remove();
                    break;
                }
            }
        });

        //添加角色与用户关系
        this.roleMenuService.saveBatch(roleMenus);
        //更新缓存
        list.addAll(roleMenus);
        this.redisUtils.set(systemCacheConfig.getRoleAndMenuCacheName(), JSON.toJSONString(list));

        return ActionResult.ok();
    }

    //endregion

    //region 查询角色关联菜单

    @GetMapping("/GetGrantedRoleMenus/{roleId}")
    @ApiOperation(value = "查询角色关联菜单")
    @Log(OperationType = OperationType.QueryList)
    @Permission(permission = "role:relate:menus")
    public ActionResult getGrantedRoleMenus(@PathVariable("roleId") String roleId)
            throws ExecutionException, InterruptedException {
        CompletableFuture<ActionResult> future = CompletableFuture.supplyAsync(() -> {
            //获取缓存数据
            Object value = this.redisUtils.get(systemCacheConfig.getRoleAndMenuCacheName());
            List<SysRoleMenu> list = JSON.parseArray(value.toString(), SysRoleMenu.class);

            list = list.stream().
                    filter(t -> t.getIsdel() == DeletionType.Undeleted.ordinal()).
                    filter(t -> t.getRoleId().equals(roleId)).
                    collect(Collectors.toList());

            return ActionResult.success(list);
        });
        return future.get();
    }

    //endregion

    //region 查询角色继承机构

    @GetMapping("/GetDelegatedRoleOrgs/{roleId}")
    @ApiOperation(value = "查询角色继承机构")
    @Log(OperationType = OperationType.QueryList)
    @Permission(permission = "role:delegate:permission")
    public ActionResult getDelegatedRoleOrgs(@PathVariable("roleId") String roleId)
            throws ExecutionException, InterruptedException {
        CompletableFuture<ActionResult> future = CompletableFuture.supplyAsync(() -> {
            //获取缓存数据
            Object value = this.redisUtils.get(systemCacheConfig.getRoleAndOrgCacheName());
            List<SysRoleOrg> list = JSON.parseArray(value.toString(), SysRoleOrg.class);

            list = list.stream().
                    filter(t -> t.getIsdel() == DeletionType.Undeleted.ordinal()).
                    filter(t -> t.getRoleId().equals(roleId)).
                    filter(t -> t.getOwnerType() == RoleType.Inherited.ordinal()).
                    collect(Collectors.toList());

            return ActionResult.success(list);
        });
        return future.get();
    }

    //endregion

    //region 机构继承角色

    @PostMapping("/DelegateRoleOrgs")
    @ApiOperation(value = "机构继承角色")
    @Log(OperationType = OperationType.DelegatePermission)
    @Permission(permission = "role:delegate:permission")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult delegateRoleOrgs(@Valid @RequestBody List<SysRoleOrg> roleOrgs) {
        List<SysRoleOrg> adds = new ArrayList<>();

        //获取缓存数据
        Object value = this.redisUtils.get(systemCacheConfig.getRoleAndOrgCacheName());
        List<SysRoleOrg> list = JSON.parseArray(value.toString(), SysRoleOrg.class);

        for (SysRoleOrg item : roleOrgs) {
            long count = list.stream().
                    filter(t -> t.getIsdel() == DeletionType.Undeleted.ordinal()).
                    filter(t -> t.getRoleId().equals(item.getRoleId())).
                    filter(t -> t.getOrgId().equals(item.getOrgId())).
                    filter(t -> t.getOwnerType() == RoleType.Own.ordinal()).
                    count();
            if (count > 0) {
                //自有角色，无需继承
                continue;
            }

            count = list.stream().
                    filter(t -> t.getIsdel() == DeletionType.Undeleted.ordinal()).
                    filter(t -> t.getRoleId().equals(item.getRoleId())).
                    filter(t -> t.getOrgId().equals(item.getOrgId())).
                    filter(t -> t.getOwnerType().equals(item.getOwnerType())).
                    count();
            //未继承该角色
            if (count == 0) {
                adds.add(item);
            }
        }

        //添加角色与用户关系
        this.roleOrgService.saveBatch(adds);
        //更新缓存
        list.addAll(adds);
        this.redisUtils.set(systemCacheConfig.getRoleAndOrgCacheName(), JSON.toJSONString(list));

        return ActionResult.ok();
    }

    //endregion

    //region 收回机构继承角色

    @PostMapping("/WithdrawRoleOrgs")
    @ApiOperation(value = "收回机构继承角色")
    @Log(OperationType = OperationType.DeleteEntity)
    @Permission(permission = "role:delegate:permission")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult withdrawRoleOrgs(@Valid @RequestBody List<SysRoleOrg> roleOrgs) {
        List<SysRoleOrg> rodels = new ArrayList<>();
        List<SysRoleUser> rudels = new ArrayList<>();

        //获取缓存数据
        Object value = this.redisUtils.get(systemCacheConfig.getRoleAndOrgCacheName());
        List<SysRoleOrg> list = JSON.parseArray(value.toString(), SysRoleOrg.class);

        value = this.redisUtils.get(systemCacheConfig.getRoleAndUserCacheName());
        List<SysRoleUser> roleUsers = JSON.parseArray(value.toString(), SysRoleUser.class);

        value = this.redisUtils.get(systemCacheConfig.getUserCacheName());
        List<SysUserDTO> users = JSON.parseArray(value.toString(), SysUserDTO.class);

        for (SysRoleOrg item : roleOrgs) {
            List<SysRoleOrg> entities = list.stream().
                    filter(t -> t.getIsdel() == DeletionType.Undeleted.ordinal()).
                    filter(t -> t.getRoleId().equals(item.getRoleId())).
                    filter(t -> t.getOrgId().equals(item.getOrgId())).
                    filter(t -> t.getOwnerType().equals(item.getOwnerType())).
                    collect(Collectors.toList());
            if (entities.size() > 0) {
                SysRoleOrg entity = entities.get(0);
                rodels.add(entity);

                List<SysUserDTO> userList = users.stream().
                        filter(t -> !StringUtils.isEmpty(t.getOrgId())).
                        filter(t -> t.getOrgId().equals(item.getOrgId())).
                        collect(Collectors.toList());

                for (SysUserDTO user : userList) {
                    List<SysRoleUser> rus = roleUsers.stream().
                            filter(t -> t.getUserId().equals(user.getId())).
                            filter(t -> t.getRoleId().equals(item.getRoleId())).
                            collect(Collectors.toList());
                    if (rus.size() > 0) {
                        rudels.addAll(rus);
                    }
                }
            }
        }

        //删除继承角色
        this.roleOrgService.removeByIds(rodels);
        this.roleUserService.removeByIds(rudels);

        //删除旧数据
        rodels.forEach(item -> {
            for (Iterator<SysRoleOrg> iterator = list.iterator(); iterator.hasNext(); ) {
                SysRoleOrg element = iterator.next();
                if (element.getId().equals(item.getId())) {
                    iterator.remove();
                    break;
                }
            }
        });

        //删除旧数据
        rudels.forEach(item -> {
            for (Iterator<SysRoleUser> iterator = roleUsers.iterator(); iterator.hasNext(); ) {
                SysRoleUser element = iterator.next();
                if (element.getId().equals(item.getId())) {
                    iterator.remove();
                    break;
                }
            }
        });

        //更新缓存
        this.redisUtils.set(systemCacheConfig.getRoleAndOrgCacheName(), JSON.toJSONString(list));
        this.redisUtils.set(systemCacheConfig.getRoleAndUserCacheName(), JSON.toJSONString(roleUsers));

        return ActionResult.ok();
    }

    //endregion

    //region 查询是否为继承角色

    @GetMapping("/IsInheritedRole/{roleId}")
    @ApiOperation(value = "查询是否为继承角色")
    @Log(OperationType = OperationType.QueryEntity)
    @Permission(permission = "role:query:list")
    public ActionResult isInheritedRole(@PathVariable("roleId") String roleId) throws Exception {
        Object value = this.redisUtils.get(systemCacheConfig.getRoleAndOrgCacheName());
        List<SysRoleOrg> roleOrgs = JSON.parseArray(value.toString(), SysRoleOrg.class);

        String orgId = this.sessionContext.getUserOrgId();
        long count = roleOrgs.stream().
                filter(t -> t.getIsdel() == DeletionType.Undeleted.ordinal()).
                filter(t -> t.getRoleId().equals(roleId)).
                filter(t -> t.getOrgId().equals(orgId)).
                filter(t -> t.getOwnerType() == RoleType.Inherited.ordinal()).
                count();

        return ActionResult.success(count > 0);
    }

    //endregion

    //region 导出角色到Excel

    @GetMapping("/ExportExcel")
    @ApiOperation(value = "导出角色到Excel")
    @Log(OperationType = OperationType.ExportData)
    @Permission(permission = "role:list:export")
    public void export(HttpServletResponse response) throws Exception {
        Object value = this.redisUtils.get(systemCacheConfig.getRoleCacheName());
        List<SysRoleDTO> roles = JSON.parseArray(value.toString(), SysRoleDTO.class);

        String orgId = this.sessionContext.getUserOrgId();
        roles = roles.stream()
                .filter(t -> !StringUtils.isEmpty(t.getOrgId()))
                .filter(t -> t.getOrgId().equals(orgId))
                .sorted(Comparator.comparing(SysRoleDTO::getSerialNumber))
                .collect(Collectors.toList());

        // 在内存操作，写出到浏览器
        ExcelWriter writer = ExcelUtil.getWriter(false);
        //自定义标题别名
        writer.addHeaderAlias("serialNumber", "序号");
        writer.addHeaderAlias("roleName", "角色名称");
        writer.addHeaderAlias("remark", "备注");
        writer.addHeaderAlias("createTime", "创建时间");

        writer.setOnlyAlias(true);
        // 一次性写出list内的对象到excel，使用默认样式，强制输出标题
        writer.write(roles, true);

        // 设置浏览器响应的格式
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode("角色信息", StandardCharsets.UTF_8.toString());
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xls");

        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        out.close();
        writer.close();
    }

    //endregion

    //region 通过Excel导入角色

    @PostMapping("/Import")
    @ApiOperation(value = "通过Excel导入角色")
    @Log(OperationType = OperationType.ImportData)
    @Permission(permission = "role:list:import")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult importRoles(MultipartFile file) throws Exception {
        ActionResult actionResult = new ActionResult();
        int errorCount = 0;

        //region 常规合法性校验

        String id = UUID.randomUUID().toString();
        String filePath = RuYiFileUtil.saveMultipartFile(file, id);
        ImportConfigDTO configDTO = this.importConfigService.getImportConfig("RoleImportConfig");
        configDTO.setExcelPath(filePath);
        errorCount = configDTO.validationDetecting();

        //endregion

        if (errorCount > 0) {
            //region 常规校验出不合规项

            actionResult.setObject(errorCount);
            id = FileNameUtil.getName(configDTO.getExcelPath()).split("\\.")[0];
            actionResult.setMessage(id);

            //endregion
        } else {
            //region 执行业务校验

            //获取角色
            Object value = this.redisUtils.get(systemCacheConfig.getRoleCacheName());
            List<SysRoleDTO> roles = JSON.parseArray(value.toString(), SysRoleDTO.class);

            //获取用户机构编号
            String orgId = this.sessionContext.getUserOrgId();
            List<SysRoleDTO> currentRoles = roles.stream()
                    .filter(t -> !StringUtils.isEmpty(t.getOrgId()))
                    .filter(t -> t.getOrgId().equals(orgId))
                    .collect(Collectors.toList());

            FileInputStream fileStream = new FileInputStream(configDTO.getExcelPath());
            Workbook workbook = new HSSFWorkbook(fileStream);
            Sheet worksheet = workbook.getSheetAt(0);

            for (int i = configDTO.getStartRow(); i <= worksheet.getLastRowNum(); i++) {
                String roleName = RuYiPoiUtil.getCellValue(worksheet.getRow(i).getCell(1)).trim();
                if (!StringUtils.isEmpty(roleName) &&
                        currentRoles.stream().anyMatch(t -> t.getRoleName().equals(roleName))) {
                    errorCount++;
                    RuYiPoiUtil.setCellComment(worksheet, i, 1, "角色名称重复！");
                }
            }

            //endregion
            if (errorCount > 0) {
                //region 常规校验出不合规项

                id = UUID.randomUUID().toString();
                String path = configDTO.getExcelPath();
                configDTO.setExcelPath(RuYiFileUtil.copyFile(path, id));

                FileOutputStream outputStream = new FileOutputStream(configDTO.getExcelPath());
                workbook.write(outputStream);

                workbook.close();
                outputStream.close();
                fileStream.close();
                //FileUtil.del(path);

                actionResult.setObject(errorCount);
                actionResult.setMessage(id);

                //endregion
            } else {
                //region 执行数据导入

                //region 读取表单数据

                InputStream inputStream = file.getInputStream();
                ExcelReader reader = ExcelUtil.getReader(inputStream);

                HashMap<String, String> headerAlias = new HashMap<>(6);
                headerAlias.put("角色名称", "roleName");
                headerAlias.put("排序", "serialNumber");
                headerAlias.put("备注", "remark");
                reader.setHeaderAlias(headerAlias);

                List<SysRole> list = reader.readAll(SysRole.class);

                //endregion

                //region 保存到数据库中

                this.roleService.saveBatch(list);

                List<SysRoleOrg> listRoleOrg = new ArrayList<>();
                list.forEach(item -> {
                    SysRoleOrg roleOrg = new SysRoleOrg();
                    roleOrg.setRoleId(item.getId());
                    roleOrg.setOrgId(orgId);
                    roleOrg.setOwnerType(RoleType.Own.ordinal());
                    listRoleOrg.add(roleOrg);
                });
                //保存机构与角色关系
                this.roleOrgService.saveBatch(listRoleOrg);

                //endregion

                //region 数据一致性维护

                //获取机构与角色关系
                value = this.redisUtils.get(systemCacheConfig.getRoleAndOrgCacheName());
                List<SysRoleOrg> roleOrgs = JSON.parseArray(value.toString(), SysRoleOrg.class);

                list.forEach(item -> {
                    SysRoleDTO roleDTO = this.modelMapper.map(item, SysRoleDTO.class);
                    roleDTO.setOrgId(orgId);
                    //添加新数据
                    roles.add(roleDTO);
                });
                //添加新数据
                roleOrgs.addAll(listRoleOrg);

                //更新缓存
                this.redisUtils.set(systemCacheConfig.getRoleCacheName(), JSON.toJSONString(roles));
                this.redisUtils.set(systemCacheConfig.getRoleAndOrgCacheName(), JSON.toJSONString(roleOrgs));

                //endregion

                //endregion
            }
        }

        actionResult.setHttpStatusCode(HttpStatus.OK.value());
        return actionResult;
    }

    //endregion

    //region 角色删除检测

    /**
     * 角色删除检测
     *
     * @param ids 编号组
     */
    private void deleteCheck(String ids) {

        Object value = this.redisUtils.get(systemCacheConfig.getRoleAndUserCacheName());
        List<SysRoleUser> roleUsers = JSON.parseArray(value.toString(), SysRoleUser.class);

        value = this.redisUtils.get(systemCacheConfig.getRoleAndMenuCacheName());
        List<SysRoleMenu> roleMenus = JSON.parseArray(value.toString(), SysRoleMenu.class);

        value = this.redisUtils.get(systemCacheConfig.getRoleAndOrgCacheName());
        List<SysRoleOrg> roleOrgs = JSON.parseArray(value.toString(), SysRoleOrg.class);

        String[] array = ids.split(",");
        for (String item : array) {
            if (roleUsers.stream().anyMatch(t -> t.getRoleId().equals(item) && t.getIsdel() == DeletionType.Undeleted.ordinal()) ||
                    roleMenus.stream().anyMatch(t -> t.getRoleId().equals(item) && t.getIsdel() == DeletionType.Undeleted.ordinal()) ||
                    roleOrgs.stream().anyMatch(t -> t.getRoleId().equals(item) && t.getIsdel() == DeletionType.Undeleted.ordinal() &&
                            t.getOwnerType().equals(RoleType.Inherited.ordinal()))) {
                throw new RuYiAdminCustomException("role has been used,can not be deleted");
            }
        }
    }

    //endregion

}
